/**
 * Server.java
 * FlightBookingCentre
 * Phillip
 * 2014��3��22�� ����2:01:33
 */
package com.controller.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import com.dao.Flight;
import com.rmi.RmiInterface;
import com.util.Constant;
import com.util.Printer;

/**
 * @author Phillip
 * 
 */
public class Server {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int PORT = 10010 + Integer.valueOf(args[0]);

		ServerSocket serverSocket = null;

		try {
			serverSocket = new ServerSocket(PORT);
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(1);
		}
		Printer.p("Airline " + args[0] + " database server is running!");
		while (true) {
			Socket incoming = null;
			try {
				incoming = serverSocket.accept();
			} catch (IOException e) {
				e.printStackTrace();
				continue;
			}
			new SocketHandler(incoming, Integer.parseInt(args[0])).start();
		}
	}

}

class SocketHandler extends Thread {
	Socket incoming;
	ServerHOPPImpl serverHOPP;
	int serverName;

	BufferedReader reader;
	PrintStream writer;

	static String syncString = new String();

	public SocketHandler(Socket incoming, int serverName) {
		// TODO Auto-generated constructor stub
		this.incoming = incoming;
		this.serverHOPP = new ServerHOPPImpl(serverName);
		this.serverName = serverName;
	}

	public void run() {

		try {
			Printer.p("new request coming...");
			writer = new PrintStream(incoming.getOutputStream());
			reader = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
			String buff = "";
			List<String> parametersStrings = new ArrayList<String>();

			while (true) {
				Printer.p("entering while loop...");
				buff = reader.readLine();
				if (buff.equals("BYE")) {
					incoming.close();
					Printer.p("broker sent BYE to disconnect!");
					break;
				}
				switch (buff) {
				case "0":
					Printer.p("broker sent a initialization request! Invoking serverHOPP.queryCity()...");
					List<String> citiesList = serverHOPP.queryCity();
					Printer.p("citylist");
					for (String city : citiesList) {
						Printer.p(city);
						writer.print(city + Constant.CR_LF);
					}
					writer.print(Constant.EOS_STRING + Constant.CR_LF);
					break;
				case "12":
					Printer.p("broker sent a query rate request,");
					parametersStrings.clear();
					for (int i = 0; i < 3; i++) {
						parametersStrings.add(reader.readLine());
					}
					Printer.p("invoking serverHOPP.queryRates()...");
					String result = serverHOPP.queryRates(this.serverName, parametersStrings.get(0), parametersStrings.get(1),
							parametersStrings.get(2));
					Printer.p("Price is " + result);
					if (result != null) {
						writer.print("12" + Constant.CR_LF);
						writer.print(result + Constant.CR_LF);
						break;
					} else {
						writer.print("12" + Constant.CR_LF);
						writer.print(null + Constant.CR_LF);
						break;
					}
				case "10":
					Printer.p("broker sent a query city request");
					parametersStrings.clear();
					for (int i = 0; i < 4; i++) {
						parametersStrings.add(reader.readLine());
					}
					Printer.p("invoking serverHOPP.queryFlights()...");
					List<Flight> resultsList = serverHOPP.queryFlights(parametersStrings.get(0), parametersStrings.get(1), parametersStrings.get(2),
							parametersStrings.get(3));
					if (resultsList == null) {
						writer.print("10" + Constant.CR_LF);
						Printer.p("no entry");
					} else {
						Printer.p("1 entry");
						writer.print("11" + Constant.CR_LF);
						for (Flight flight : resultsList) {
							Printer.p("flightNO is " + flight.getFligthNOString());
							writer.print(flight.getAirlineString() + Constant.CR_LF);
							writer.print(flight.getFligthNOString() + Constant.CR_LF);
							writer.print(flight.getDeptCityString() + Constant.CR_LF);
							writer.print(flight.getDeptDate() + Constant.CR_LF);
							writer.print(flight.getArriDate() + Constant.CR_LF);
							writer.print(flight.getDeptTime() + Constant.CR_LF);
							writer.print(flight.getArriTime() + Constant.CR_LF);
							writer.print(flight.getDeptAirportString() + Constant.CR_LF);
							writer.print(flight.getArriAirportString() + Constant.CR_LF);
							writer.print(flight.getPlaneString() + Constant.CR_LF);
							writer.print(flight.getClassEnum() + Constant.CR_LF);
							writer.print(flight.getPriceString() + Constant.CR_LF);
						}
						writer.print(Constant.EOS_STRING + Constant.CR_LF);
					}
					break;
				case "2":
					Printer.p("broker sent a book request");
					parametersStrings.clear();
					for (int i = 0; i < 8; i++) {
						parametersStrings.add(reader.readLine());
					}
					String resultString = "";
					Printer.p("ready to entering sync block!");
					synchronized (syncString) {
						Printer.p("entering sync block and invoking serverHOPP.book()...");
						resultString = serverHOPP.book(this.serverName, parametersStrings.get(0), parametersStrings.get(1), parametersStrings.get(2),
								parametersStrings.get(3), parametersStrings.get(4), parametersStrings.get(5), parametersStrings.get(6),
								parametersStrings.get(7));
					}
					Printer.p("book result is " + resultString);
					writer.print("2" + Constant.CR_LF);
					writer.print(resultString + Constant.CR_LF);
					writer.print(Constant.EOS_STRING + Constant.CR_LF);
					break;
				case "13":
					Printer.p("broker sent a query airline request");
					String tempString = reader.readLine();
					String tempString2 = reader.readLine();
					tempString = serverHOPP.queryAirline(tempString, tempString2);

					writer.print(tempString + Constant.CR_LF);
					break;
				default:
					break;
				}
			}
			Printer.p("disconnecting with database.");
			serverHOPP.disconnect();
		} catch (IOException e) {
			e.printStackTrace();
			return;
		}
	}
}